package minmax;

import java.util.Iterator;

/**
 * allows to synchronize two game states and use them for different players
 * 
 * @author alex
 *
 * @param <M> is type of moves
 */
public class GamePair<M extends GameMove> implements GameState<M> {

	/**
	 * state for the first player
	 */
	private GameState<M> first;
	
	/**
	 * state for the second player
	 */
	private GameState<M> second;
	
	/**
	 * create pair
	 * 
	 * @param first is a state
	 * @param second is a state
	 */
	public GamePair(GameState<M> first, GameState<M> second) {
		if (first == null || second == null) {
			throw new NullPointerException();
		}
		this.first = first;
		this.second = second;
	}
	
	/**
	 * @return an underlying state
	 */
	public GameState<M> unfold() {
		return first;
	}
	
	@Override
	public void move(M step) {
		first.move(step);
		second.move(step);
	}

	@Override
	public void backtrack() {
		first.backtrack();
		second.backtrack();
	}

	@Override
	public Iterator<M> moves() {
		return first.moves();
	}

	@Override
	public boolean canMove(M move) {
		return first.canMove(move);
	}

	@Override
	public boolean player() {
		return first.player();
	}

	@Override
	public int evaluate(boolean maximize) {
		return first.player() ? second.evaluate(maximize) : first.evaluate(maximize);
	}

	@Override
	public boolean isFinished() {
		return first.isFinished();
	}

	@Override
	public GameOutcome outcome() {
		return first.outcome();
	}

	@Override
	public int hashCode() {
		return 31 * first.hashCode() + second.hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		return first.equals(obj) && second.equals(obj);
	}

	@Override
	public GamePair<M> clone() {
		return new GamePair<M>(first, second);
	}

	@Override
	public String toString() {
		// since states are the same we do keep the output simple
		return first.toString();
	}
	
}
